package xdu.lz.stage2_design_pattern.chapter16_two_phrase_terminated_pattern;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AppServer extends Thread{

    private final int port;

    private static final int DEFAULT_PORT = 10086;

    private volatile boolean start = true;

    //已经连接的socket，传入ClientHandler，提交任务
    private List<ClientHandler> clientHandlers = new ArrayList<>();

    //线程池用来处理socket连接
    private final ExecutorService executor = Executors.newFixedThreadPool(10);

    //服务端引用
    private ServerSocket serverSocket;

    public AppServer(){
        this(DEFAULT_PORT);
    }

    public AppServer(int port) {
        this.port = port;
    }

    @Override
    public void run() {
        try {
            this.serverSocket = new ServerSocket(this.port);
            //不断监听连接，每一个连接就创建一个线程去服务
            while (start){
                //阻塞监听客户端连接
                Socket client = serverSocket.accept();
                //拿到连接后去封装连接的任务
                ClientHandler clientHandler = new ClientHandler(client);
                clientHandlers.add(clientHandler);
                //执行runnable,每个runnable被线程池的每个线程所执行
                executor.submit(clientHandler);
            }
        } catch (IOException e) {
            System.out.println("服务端主动关闭，serverSocket监听端口异常...");
            throw new RuntimeException(e);
        }finally {
            this.dispose();
        }
    }

    private void dispose() {
        //处理客户端的线程每个都要关闭
        clientHandlers.stream().forEach(ClientHandler ::stop);
        //关闭线程池
        executor.shutdown();
    }


    public void shutdown() throws IOException {
        //先关闭服务端线程，关闭完后会执行finally块中的dispose
        this.start = false;
        this.interrupt();
        //在关闭服务端的socket
        this.serverSocket.close();
    }

}
